home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / tutorials / geometer / doexec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  10.2 KB  |  445 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. #include <gl.h>
  19. #include <device.h>
  20. #include <stdio.h>
  21. #include <unistd.h>
  22. #include <bstring.h>
  23. #include <errno.h>
  24. #include <assert.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/signal.h>
  28. #include <sys/fcntl.h>
  29. #include <sys/errno.h>
  30. #include <sys/stat.h>
  31. #include <netinet/in.h>
  32. #include <sys/time.h>
  33. #include "gizmo.h"
  34. #include "generic.h"
  35. #include "cmds.h"
  36. #ifdef __cplusplus
  37. #include <osfcn.h>
  38. #include <stdarg.h>
  39. #else
  40. #include <varargs.h>
  41. #endif
  42.  
  43. int    gd;
  44. gizmo_t *gizmoptr;
  45.  
  46. /*    gd = qgetfd();    XXX */
  47.  
  48.  
  49. gizmo_t        browsegizmo = {
  50.     "/usr/lib/jot/browsegizmo",          /* name */
  51.     0,                 /* fd */
  52.     0,                 /* pid */ 
  53.     0,                 /* llx */ 
  54.     0,                 /* lly */ 
  55.     0,                 /* xsize */ 
  56.     0,                 /* ysize */ 
  57.     0,                 /* state */ 
  58.     0,                 /* initme */ 
  59.     0,                 /* killme */ 
  60.     0,                 /* next */
  61.  
  62. };
  63.  
  64. static void senddev(gizmo_t *gp, long dev)
  65. {
  66.     if (gp->fd == 0) return;
  67.     if (write(gp->fd, &dev, sizeof(dev)) < 0)  {
  68.     perror("writing stream message");
  69.     exit(1);
  70.     }
  71. }
  72.  
  73. static void senddevval(gizmo_t *gp, long dev, long val)
  74. {
  75.     long buf[2];
  76.     
  77.     if (gp->fd == 0) return;
  78.     buf[0] = dev;
  79.     buf[1] = val;
  80.     if (write(gp->fd, buf, sizeof(buf)) < 0)  {
  81.     perror("writing stream message");
  82.     exit(1);
  83.     }
  84. }
  85.  
  86. static long readbuf(int fd, char *p, int totbytes)
  87. {
  88.     int nbytes, n;
  89.  
  90.     nbytes = 0;
  91.     while (nbytes < totbytes) {
  92.     if ( (n=read(fd,p+nbytes,totbytes-nbytes)) < 0) {
  93.         if (errno == EINTR) continue;
  94.         perror("Read failure");
  95.         return -1;
  96.     }
  97.     if (n == 0)
  98.         break;
  99.     nbytes += n;
  100.     }
  101.     return nbytes;
  102. }
  103.  
  104. static long readlongfromsocket(gizmo_t *gp)
  105. {
  106.     long val;
  107.  
  108.     if (gp->fd == 0) return 0;
  109.     if (readbuf(gp->fd,(char *)&val,sizeof(val)) < 0) {
  110.         (void)fprintf(stderr,"unknown data from socket\n");
  111.         exit(0);
  112.     }
  113.     return val;
  114. }
  115.  
  116. static void sendstringtogizmo(gizmo_t *gp, long type, char *s)
  117. {
  118.     long    buf[210], i = 2;
  119.  
  120.     buf[0] = type;
  121.     buf[1] = -1;
  122.  
  123.     if (!s)
  124.     goto lastwrite;
  125.     do {
  126.     buf[i++] = type;
  127.     buf[i++] = *s++;
  128.     } while (*s);
  129. lastwrite:
  130.     if (write(gp->fd, buf, (unsigned int)(i*sizeof(long))) < 0) {
  131.     if (gp && gp->pid) (void)kill(gp->pid,SIGTERM);
  132.     }
  133. }
  134.  
  135.  
  136. /* The first item in the arg list must be a pointer to gizmo_t. The rest are
  137.  * gizmo specific.
  138.  */
  139.  
  140. /*VARARGS*/
  141. #ifdef __cplusplus
  142. void doexec(gizmo_t *gizptr ...)
  143. #else
  144. void doexec(va_alist)
  145. va_dcl
  146. #endif
  147. {
  148.     struct    sockaddr_in saddr;
  149.     int        len, sock1, child, fd;
  150.     char    charportnum[100], *gargv[20];
  151.     struct    stat statbuf;
  152.     va_list    ap;
  153.     gizmo_t     *gp;
  154.     long        argno;
  155.  
  156.  
  157. #ifdef __cplusplus
  158.     va_start(ap, gizptr);
  159.     gp = gizptr;
  160. #else
  161.     va_start(ap);
  162.     gp = (gizmo_t *)va_arg(ap, gizmo_t *);
  163. #endif
  164.     if (-1 == stat(gp->name,&statbuf)) {
  165.     perror("stat error");
  166.     exit(1);
  167.     }
  168.  
  169.     sock1 = socket(AF_INET, SOCK_STREAM, 0);
  170.     if(sock1 < 0) {
  171.     perror("error opening socket");
  172.     exit(1);
  173.     }
  174.  
  175.     /* Create name for parent socket on local machine. */
  176.  
  177.     saddr.sin_family = AF_INET;
  178.     saddr.sin_addr.s_addr = INADDR_ANY;
  179.     saddr.sin_port = 0;
  180.     if(bind(sock1, &saddr, sizeof(saddr))) {
  181.     perror("binding parent socket");
  182.     (void)close(sock1);
  183.     exit(1);
  184.     }
  185.  
  186.     /* Find out port number assigned to parent socket. */
  187.  
  188.     len = sizeof(saddr);
  189.     if(getsockname(sock1, &saddr, &len)) {
  190.     perror("getting parent socket name");
  191.     (void)close(sock1);
  192.     exit(1);
  193.     }
  194.  
  195.     (void)listen(sock1, 1 /* max size of queue of waiting connectors */);
  196.     child = (int)fork();
  197.     if(child) {
  198. retry:
  199.     fd = accept(sock1, 0, 0);
  200.     if(fd == -1) {
  201.         if (errno == EINTR)
  202.         goto retry;
  203.         (void)fprintf(stderr, "Failed to open gizmo.\nError %d", errno);
  204.         (void)kill(child,SIGKILL);
  205.         exit(1);
  206.     }
  207.     gp->fd = fd;
  208.     gp->pid = child;
  209.     if (gizmoptr == 0) {
  210.         gizmoptr = gp;
  211.         gp->next = 0;
  212.     } else {
  213.         gp->next = gizmoptr;
  214.         gizmoptr = gp;
  215.     }
  216.     gp->state = GIZMOSTATE_OPEN;
  217.     (void)close(sock1);
  218.     } else {
  219.     (void)close(sock1);
  220.     (void)sprintf(charportnum, "%d", (int)ntohs(saddr.sin_port));
  221.     gargv[0] = gp->name;
  222.     gargv[1] = charportnum;
  223.     for (argno = 2; gargv[argno] = (char *)va_arg(ap, char *); argno++) {
  224.         /*printf("%s\n", gargv[argno]);*/
  225.         ;
  226.     }
  227.     (void)execvp(gp->name, gargv);
  228.     perror("exec failed");
  229.     exit(1);
  230.     }
  231.     va_end();
  232. }
  233.  
  234. /*
  235.  * find the gizmo with the correct pid.  We have gotten a signal that it 
  236.  * died.
  237.  */
  238.  
  239. void murdergizmos()
  240. {
  241.     gizmo_t *gp;
  242.  
  243.     for (gp = gizmoptr; gp; gp = gp->next) {
  244.     (void)kill(gp->pid,SIGTERM);
  245.     (void)kill(gp->pid,SIGTERM);
  246.     (void)kill(gp->pid,SIGTERM);
  247.     (void)kill(gp->pid,SIGTERM);
  248.     /* There!  That ought to kill it fer sure! */
  249.     }
  250. }
  251.  
  252. /* Event reception *********************************************************/
  253.  
  254. long getqevent(long *val, long *dev)
  255. {
  256.     short    sval;
  257.  
  258.     if (qtest() == 0) {*dev = 0; return 0; }
  259.     *dev = qread(&sval);
  260.     *val = sval;
  261.     return 1;
  262. }
  263.  
  264. int rawqread(long *val)
  265. {
  266.     long    dev, n;
  267.     fd_set    fdset;
  268.     long    buf[2];
  269.     struct timeval    timeout, *tp = &timeout;
  270.     gizmo_t     *gp;
  271.  
  272.     while(1) {
  273. tryagain:
  274.     if (getqevent(val, &dev))
  275.         return dev;
  276.     FD_ZERO(&fdset);
  277.     FD_SET(gd, &fdset);
  278.     for (gp = gizmoptr; gp; gp = gp->next) {
  279.         FD_SET(gp->fd, &fdset); /* do this for all gizmos */
  280.     }        
  281.     tp = 0;
  282.     while ((n = select(FD_SETSIZE, &fdset, (fd_set *)0, (fd_set *)0, tp)) < 0) {
  283.         if (errno == EINTR)    {
  284.         goto tryagain;
  285.         }
  286.         perror("select");
  287.         (void)fprintf(stderr, "select error");
  288.     }
  289.     for (gp = gizmoptr; gp; gp = gp->next) {
  290.         if(FD_ISSET(gp->fd, &fdset)) { /* do this for all gizmos */
  291.         if((n = readbuf(gp->fd, (char *)buf, sizeof(buf))) < 0) {
  292.             perror("Error reading stream message");
  293.             (void)kill(gp->pid,SIGKILL);
  294.         }
  295.         if (n == 0) {
  296.             continue;
  297.         }
  298.         /* setmainwindow(); */
  299.         *val = buf[1];
  300.         return buf[0];
  301.         }
  302.     }
  303.     if(FD_ISSET(gd, &fdset)) {  /* grapics input queue non-empty */
  304.         (void)getqevent(val, &dev);
  305.         return dev;
  306.     }
  307.     }
  308. }
  309.  
  310. extern long smearflag;
  311. extern short defaultwidth;
  312.  
  313. long cookedqread(long *val)
  314. {   
  315.     long dev;
  316.     
  317.     dev = rawqread(val);
  318.     if (dev == KEYBD && (getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY))) {
  319.     switch (*val) {
  320.         case 'n':
  321.             return NEWCMD;
  322.         case 'o':
  323.             return OPENCMD;
  324.         case 's':
  325.             return SAVECMD;
  326.         case 'S':
  327.             return SAVEASCMD;
  328.         case 'p':
  329.             return PRINTCMD;
  330.         case 'q':
  331.             return QUITCMD;
  332.         case 'Q':
  333.             return QUITDAMMIT;
  334.         case 'd':    // delete
  335.             return DELSELECTION;
  336.         case 'e':    // edit
  337.             return EDITGEOM;
  338.             case '0': case '1': case '2': case '3':
  339.         case '4': case '5': case '6': case '7':
  340.             return C0 + *val - '0';
  341.         case 'x':
  342.         smearflag = 1 - smearflag; break;
  343.         case 'l':
  344.         defaultwidth = 3 - defaultwidth;
  345.         break;
  346.     }
  347.     }
  348.     return dev;    
  349. }
  350.  
  351. void centerovercursor(long *llx, long *urx, long *lly, long *ury, long width, long height)
  352. {
  353.     *llx = getvaluator(MOUSEX) - width/2;
  354.     *ury = getvaluator(MOUSEY) + height/2;
  355.     if (*llx + width > getgdesc(GD_XPMAX))
  356.         *llx = getgdesc(GD_XPMAX) - width -10;
  357.     if (*ury - height < 0)
  358.         *ury = height+10;
  359.     *lly = *ury - height;
  360.     *urx = *llx + width;
  361. }
  362.  
  363. /* Exec-ing and killing gizmos ***********************************************/
  364.  
  365. static void openbrowsegizmo(gizmo_t *gp, char *title, char *dir,
  366.                             char *buttonstring, char *accepttitle)
  367. {
  368.     char cx[10], cy[10];
  369.     long width = 340;
  370.     long height = 450;
  371.     long llx, lly, urx, ury;
  372.  
  373.     if (gp->state == GIZMOSTATE_OPEN) {
  374.     /* need to init x, y, title, dir and buttonstring too */
  375.         centerovercursor(&llx,  &urx, &lly, &ury, width, height);
  376.     senddevval(gp,GIZMOXORG ,llx);
  377.     senddevval(gp,GIZMOYORG,lly);
  378.     if (title) sendstringtogizmo(gp, TITLESTRDEV, title);
  379.     if (dir) sendstringtogizmo(gp, DIRNAMEDEV ,dir);
  380.     /* always send buttonstring to clear it if null */
  381.     sendstringtogizmo(gp, BUTTONSTRDEV ,buttonstring );
  382.     sendstringtogizmo(gp, ACCEPTSTRDEV ,accepttitle );
  383.     senddev(gp, REINITEND);
  384.     return;
  385.     }
  386.     centerovercursor(&llx, &urx, &lly, &ury, width, height);
  387.     (void)sprintf(cx, "%d", (int)llx);
  388.     (void)sprintf(cy, "%d", (int)lly);
  389.     doexec(gp, "0", cx, cy, title, dir, buttonstring, accepttitle, 0);
  390.     senddev(gp,GIZMOINITEND);
  391. }
  392.  
  393. long getfilename(char *title, 
  394.         char *filename, 
  395.         char *buttonstring, 
  396.         char *dir, 
  397.             char *acceptbuttitle, 
  398.             long (*filetype)(char *))
  399. {
  400.     long dev, val;
  401.     
  402.     *filename = 0;
  403.     openbrowsegizmo(&browsegizmo, title, dir, buttonstring, acceptbuttitle);
  404.     if (!browsegizmo.fd)
  405.     return -1;
  406.     while (1) {
  407.     dev = cookedqread(&val);
  408.     switch (dev) {
  409.         case CREATEDEV:
  410.         val = readlongfromsocket(&browsegizmo);
  411.         /* this means they want to create a new thing */
  412.         /* send FREEZE not ABORT, so process stays around */
  413.         senddev(&browsegizmo, WINFREEZE);
  414.         qreset(); qenter(REDRAW, 0);
  415.         return 0;
  416.         case DIRNAMEDEV:
  417.         if (0 > readbuf(browsegizmo.fd, dir, (int)val)) {
  418.             perror("Error reading stream message");
  419.             (void)kill(browsegizmo.pid,SIGKILL);
  420.         }
  421.         break;
  422.         case FILENAMEDEV:
  423.         if (0 > readbuf(browsegizmo.fd, filename, (int)val)) {
  424.             perror("Error reading stream message");
  425.             (void)kill(browsegizmo.pid,SIGKILL);
  426.             *filename = 0;
  427.             return 0;
  428.         }
  429.         if (filetype && (!(*filetype)(filename))){
  430.             *filename = 0;
  431.             return getfilename(title, filename, buttonstring, dir, acceptbuttitle, filetype);
  432.         }
  433.         qreset(); qenter(REDRAW, 0);
  434.         return 1;
  435.         case ABORT: /*  user chose CANCEL*/
  436.         *filename = 0;
  437.         qreset(); qenter(REDRAW, 0);
  438.         return -1;
  439.         default:
  440.         senddev(&browsegizmo, POKEGIZMO);
  441.         break;
  442.     }
  443.     }
  444. }
  445.